home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993 October: Windmill on DISC / ADC Developer CD (1993-10) (''Windmill On DISC'')_iso / Dev.CD Oct 93.iso / System Software / U.S. System Software / System 7 Pro™ Beta 11 / Development Tools / Sample Code / Messaging Service Access Module / Internet PMSAM / Internet PMSAM source / gatewaystuff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-28  |  15.4 KB  |  635 lines  |  [TEXT/MPS ]

  1. /*-------------------------------------------------------------------
  2.  
  3. AOCE Post Office Protocol (POP) / Simple Mail Transfer Protocol (SMTP)
  4. Mail Service Access Module
  5.  
  6. written by Steve Falkenburg-- MacDTS
  7. ©1991-1993 Apple Computer, Inc.
  8.  
  9. --------------
  10. change history
  11. --------------
  12.  
  13. SJF        02/19/93    update for beta build    b1
  14. SJF        10/29/92    update to a11            a11
  15. SJF        06/08/92    update to a8            a8
  16. SJF        02/15/92    first working version    a4.5
  17. SJF        10/16/91    initial coding            a3
  18.  
  19. ---------------------------------------------------------------------*/
  20.  
  21. #ifndef __TRAPS__
  22. #include <Traps.h>
  23. #endif
  24.  
  25. #ifndef __GESTALTEQU__
  26. #include <GestaltEqu.h>
  27. #endif
  28.  
  29. #ifndef __OCE__
  30. #include <OCE.h>
  31. #endif
  32.  
  33. #ifndef __OCEAUTHDIR__
  34. #include <OCEAuthDir.h>
  35. #endif
  36.  
  37. #ifndef __OCEERRORS__
  38. #include <OCEErrors.h>
  39. #endif
  40.  
  41. #include <string.h>
  42.  
  43. #ifdef applec
  44. #include <strings.h>
  45. #endif
  46.  
  47. #include "const.h"
  48. #include "gwerrors.h"
  49. #include "mytypes.h"
  50. #include "globals.h"
  51. #include "utils.h"
  52. #include "trapavailable.h"
  53. #include "authstuff.h"
  54. #include "gatewaystuff.h"
  55.  
  56.  
  57. // think c compatibility
  58. #ifndef    _GestaltDispatch
  59. #define    _GestaltDispatch    _Gestalt
  60. #endif
  61.  
  62.  
  63. // InitGatewayStuff
  64. //
  65. // called when the gateway is first launched.  initializes the global variables of importance
  66. // to AOCE and reads in the slot information for all of the gateways slots.
  67. //
  68. OSErr InitGatewayStuff(void)
  69. {
  70.     OSErr err;
  71.     DirParamBlock dirBlock;
  72.     MSAMParam msBlock;
  73.     
  74.     gHLEventAdd = gHLEventRemove = nil;
  75.     
  76.     gNumSlots = 0;
  77.         
  78.     // get the local identity for dir manager calls
  79.  
  80.     err = InitAuthStuff();
  81.     if (err!=noErr)
  82.         return err;
  83.         
  84.     // get creation ID of the AOCE setup PAB
  85.     
  86.     err = DirGetOCESetupRefNum(&dirBlock,false);
  87.     if (err!=noErr) {
  88.         ExitAuthStuff();
  89.         return err;
  90.     }
  91.     
  92.     OCECopyCreationID(&dirBlock.dirGetOCESetupRefNumPB.oceSetupRecordCID,&gAOCESetupCID);
  93.     gAOCESetupDSRef = dirBlock.dirGetOCESetupRefNumPB.dsRefNum;
  94.     
  95.     // get creation ID of gateway setup record
  96.     
  97.     err = PMSAMGetMSAMRecord(&msBlock);
  98.     if (err!=noErr) {
  99.         ExitAuthStuff();
  100.         return err;
  101.     }
  102.     OCECopyCreationID(&msBlock.pmsamGetMSAMRecord.msamCID,&gMSAMCID);
  103.  
  104.     err = ReadGatewaySlotInformation();
  105.     if (err==kMailNoSuchSlot) {
  106.         DebugStr("\pQueue not registered yet, but we'll continue anyway, since it will be sometime");
  107.         MarkSlotInformationDirty();
  108.         err = noErr;
  109.     }
  110.     
  111.     if (err!=noErr) {
  112.         ExitAuthStuff();
  113.         return err;
  114.     }
  115.     
  116.     gAOCEInited = true;
  117.     
  118.     return err;
  119. }
  120.  
  121.  
  122. // ActivateSlot
  123. //
  124. // sets up a slot spec as active and ready to accept mail, this call gets refs to the in and out
  125. // queues for the slot
  126. //
  127. OSErr ActivateSlot(SlotSpec *slot)
  128. {
  129.     MSAMParam msParam;
  130.     OSErr err;
  131.     
  132.     // get slot queues
  133.         
  134.     msParam.pmsamOpenQueues.msamSlotID = slot->slotID;
  135.     err = PMSAMOpenQueues(&msParam);
  136.     
  137.     // set up other slot info
  138.     
  139.     slot->active = true;
  140.     slot->inQueue = msParam.pmsamOpenQueues.inQueueRef;
  141.     slot->outQueue = msParam.pmsamOpenQueues.outQueueRef;
  142.     slot->lastCheckGet = 0;
  143.     slot->lastCheckPut = 0;
  144.     slot->enabled = true;
  145.     slot->retryPut = 0;
  146.     slot->retryGet = 0;
  147.     slot->retryPutError = 0;
  148.     slot->retryGetError = 0;
  149.  
  150.  
  151.     if (err!=noErr) {
  152.         slot->enabled = false;
  153.     }
  154.  
  155.     return err;
  156. }
  157.  
  158.  
  159. // CheckSlotRefresh
  160. //
  161. // called when we need to see if the slot information needs to be updated.  calls
  162. // ReadGatewaySlotInformation to re-read the information
  163. //
  164. OSErr CheckSlotRefresh(void)
  165. {
  166.     OSErr err;
  167.     
  168.     err = noErr;
  169.     
  170.     if (gUpdateSlotInformation) {
  171.         err = ReadGatewaySlotInformation();
  172.         if (err==kMailNoSuchSlot) {
  173.             // no queue for our slot yet... try again later.
  174.             err = noErr;
  175.             DebugStr("\pno queue yet... try again later");
  176.             MarkSlotInformationDirty();
  177.         }
  178.     }
  179.     return err;
  180. }
  181.  
  182.  
  183. // MarkSlotInformationDirty
  184. //
  185. // marks the slot database for refresh at main event loop time
  186. //
  187. void MarkSlotInformationDirty(void)
  188. {
  189.     gUpdateSlotInformation = true;
  190. }
  191.  
  192.  
  193. // ReadGatewaySlotInformation
  194. // 
  195. // called in response to a launch *or* in response to a change in the slot database,
  196. // this call rebuilds the internal database of slots from the AOCE Setup Directory
  197. //
  198. OSErr ReadGatewaySlotInformation(void)
  199. {
  200.     short slotIndex;
  201.     OSErr err;
  202.     
  203.     TraceExecution("\pReadGatewaySlotInformation");
  204.  
  205.     gUpdateSlotInformation = false;
  206.     gNumSlots = 0;
  207.     
  208.     // set up the skeleton slot database containing only the CID to the mailservice records
  209.     
  210.     err = GetParseSetupAttributes(&gMSAMCID,kMailServiceAttrTypeNum,AddSlotCallback,0L);
  211.     if (err!=noErr)
  212.         return err;
  213.     
  214.     // for each slot, get the slot data from the mailservice record and activate the slot
  215.     
  216.     for (slotIndex=0;slotIndex<gNumSlots && err==noErr;slotIndex++) {
  217.         err = GetMailServiceInfo(&gSlotDatabase[slotIndex].slotCID,&gSlotDatabase[slotIndex]);
  218.         if (err==noErr)
  219.             err = ActivateSlot(&gSlotDatabase[slotIndex]);
  220.     }
  221.     
  222.     gAuthRefresh = true;    // re-read the directory external identities
  223.     
  224.     if (gAOCEInited && (gNumSlots==0)) {    // if we don't have any slots, and we didn't just launch,
  225.         gDone = true;                        // then quit MSAM
  226.         DebugStr("\pexiting since no slots");
  227.     }
  228.             
  229.     return err;
  230. }
  231.  
  232.  
  233. // GetMailServiceInfo
  234. //
  235. // given a creation ID to a mailservice record ID and a storage area in the slot database, this function fills
  236. // in the slot database information for a particular slot.
  237. //
  238. OSErr GetMailServiceInfo(CreationID *cid,SlotSpecPtr theSlot)
  239. {
  240.     PackedRecordID packedAssocDir;
  241.     RecordID assocDir;
  242.     CreationID *dirCID;
  243.     OSErr err;
  244.     OSType dirType;
  245.     RString comment;
  246.     AttributeType attrTypeString;
  247.     
  248.     // get slot id
  249.     
  250.     err = GetSingleValueAttribute(cid,OCEGetIndAttributeType(kSlotIDAttrTypeNum),&theSlot->slotID,sizeof(short));
  251.     if (err!=noErr)
  252.         return err;
  253.     
  254.     // get standard slot information
  255.     
  256.     err = GetSingleValueAttribute(cid,OCEGetIndAttributeType(kStdSlotInfoAttrTypeNum),&theSlot->stdInfo,sizeof(MailStandardSlotInfoAttribute));
  257.     if (err!=noErr)
  258.         return err;
  259.     theSlot->active = theSlot->stdInfo.active;
  260.     
  261.     // get associated directory
  262.     
  263.     err = GetSingleValueAttribute(cid,OCEGetIndAttributeType(kAssoDirectoryAttrTypeNum),&packedAssocDir,sizeof(PackedRecordID));
  264.     if (err!=noErr)
  265.         return err;
  266.  
  267.     // get info from associated directory
  268.     
  269.     OCEUnpackRecordID(&packedAssocDir,&assocDir);
  270.     dirCID = &assocDir.local.cid;
  271.     
  272.     // get directory type
  273.         
  274.     err = GetSingleValueAttribute(dirCID,OCEGetIndAttributeType(kDirTypeAttrTypeNum),&dirType,sizeof(OSType));
  275.     if (err!=noErr)
  276.         return err;
  277.     
  278.     // get directory name
  279.     
  280.     err = GetSingleValueAttribute(dirCID,OCEGetIndAttributeType(kRealNameAttrTypeNum),&theSlot->directoryName,sizeof(RString));
  281.     if (err!=noErr)
  282.         return err;
  283.     
  284.     // get directory discriminator
  285.     
  286.     err = GetSingleValueAttribute(dirCID,OCEGetIndAttributeType(kDiscriminatorAttrTypeNum),
  287.         &theSlot->discriminator,sizeof(DirDiscriminator));
  288.     if (err!=noErr)
  289.         return err;
  290.  
  291.     // get directory comment
  292.     
  293.     err = GetSingleValueAttribute(dirCID,OCEGetIndAttributeType(kCommentAttrTypeNum),&comment,sizeof(RString));
  294.     if (err!=noErr)
  295.         return err;
  296.     
  297.     //
  298.     // code to get specific slot information
  299.     //
  300.     
  301.     // now we get all the specific information at the same time
  302.         
  303.     OCECToRString(kSpecInfoAttr,smRoman,(RString*)&attrTypeString,kRStringMaxBytes);
  304.     err = GetSingleValueAttribute(cid,&attrTypeString,&theSlot->specInfo,sizeof(SpecificSlotInfo));
  305.     if (err!=noErr)
  306.         return err;
  307.     
  308.     // note that we don't get the name and password -- these are filled in by the auth mgr
  309.     // refresh mechanism, dispatched by setting a flag from the auth mgr queue notification
  310.     // proc, and filled in at event loop time
  311.     
  312.     theSlot->dirIdentity.userName[0] = 0;
  313.     theSlot->dirIdentity.password[0] = 0;
  314.     theSlot->dirIdentity.valid = false;
  315.     
  316.     return err;
  317. }
  318.  
  319.  
  320. // GetParseSetupAttributes
  321. //
  322. // this routine provides a generic lookup routine to iterate through attributes in a
  323. // personal directory record.  it's used to read the slot setup information out of the
  324. // aoce setup directory
  325. //
  326. OSErr GetParseSetupAttributes(CreationID *cid,short attrType,ForEachAttrValue callBack,long clientData)
  327. {
  328.     DirParamBlock dirBlock;
  329.     Ptr buff;
  330.     Boolean moreData;
  331.     OSErr err;
  332.     RecordIDPtr recordList[1];
  333.     AttributeTypePtr attrList[1];
  334.     RecordID recordID;
  335.     
  336.     MakePersonalRecordID(&recordID,cid);
  337.     
  338.     recordList[0] = (RecordIDPtr)&recordID;
  339.     attrList[0] = OCEGetIndAttributeType(attrType);
  340.     buff = NewPtrChk(kAttrBufferSize);
  341.     if (MemError()!=noErr)
  342.         return MemError();
  343.     
  344.     ClearBuffer(&dirBlock,sizeof(DirParamBlock));
  345.         
  346.     dirBlock.header.clientData = clientData;
  347.     dirBlock.lookupGetPB.serverHint.aNet = 0;
  348.     dirBlock.lookupGetPB.serverHint.aNode = 0;
  349.     dirBlock.lookupGetPB.serverHint.aSocket = 0;
  350.     dirBlock.lookupGetPB.dsRefNum = gAOCESetupDSRef;
  351.     dirBlock.lookupGetPB.identity = gLocalIdentity;
  352.     dirBlock.lookupGetPB.aRecordList = recordList;
  353.     dirBlock.lookupGetPB.attrTypeList = attrList;
  354.     dirBlock.lookupGetPB.recordIDCount = 1;
  355.     dirBlock.lookupGetPB.attrTypeCount = 1;
  356.     dirBlock.lookupGetPB.includeStartingPoint = false;
  357.     dirBlock.lookupGetPB.getBuffer = buff;
  358.     dirBlock.lookupGetPB.getBufferSize = kAttrBufferSize;
  359.     dirBlock.lookupGetPB.startingRecordIndex = 1;
  360.     dirBlock.lookupGetPB.startingAttrTypeIndex = 1;
  361.     dirBlock.lookupParsePB.eachRecordID = nil;
  362.     dirBlock.lookupParsePB.eachAttrType = nil;
  363.     dirBlock.lookupParsePB.eachAttrValue = callBack;
  364.     OCESetCreationIDtoNull(&dirBlock.lookupGetPB.startingAttribute.cid);
  365.     
  366.     do {
  367.         err = DirLookupGet(&dirBlock,false);
  368.         if (err==kOCEMoreData)
  369.             moreData = true;
  370.         else
  371.             moreData = false;
  372.         if (err==noErr || err==kOCEMoreData) {
  373.             err = DirLookupParse(&dirBlock,false);
  374.             if (err!=noErr)
  375.                 moreData = false;    // this could be kOCEMoreAttrValue (buffer not big enough)
  376.                                     // or kOCEMoreData (didn't have permission to read)
  377.         }
  378.     } while (moreData);
  379.     
  380.     DisposPtrChk(buff);
  381.     
  382.     return err;
  383. }
  384.  
  385.  
  386. // GetSingleValueAttribute
  387. //
  388. // this routine returns a single attribute value from a record.  it's used to get information out
  389. // of the slot setup information
  390. //
  391. OSErr GetSingleValueAttribute(CreationID *cid,AttributeType *attribType,void *attrBuffer,Size attrBufferSize)
  392. {
  393.     DirParamBlock dirBlock;
  394.     Ptr buff;
  395.     OSErr err;
  396.     RecordIDPtr recordList[1];
  397.     AttributeTypePtr attrList[1];
  398.     RecordID recordID;
  399.     AttributeCopyInfo callbackInfo;
  400.     
  401.     callbackInfo.buffer = attrBuffer;
  402.     callbackInfo.bufferSize = attrBufferSize;
  403.     
  404.     MakePersonalRecordID(&recordID,cid);
  405.     
  406.     recordList[0] = (RecordIDPtr)&recordID;
  407.     attrList[0] = attribType;
  408.     buff = NewPtrChk(kAttrBufferSize);
  409.     if (MemError()!=noErr)
  410.         return MemError();
  411.     
  412.     ClearBuffer(&dirBlock,sizeof(DirParamBlock));
  413.         
  414.     dirBlock.header.clientData = (long)&callbackInfo;
  415.     dirBlock.lookupGetPB.serverHint.aNet = 0;
  416.     dirBlock.lookupGetPB.serverHint.aNode = 0;
  417.     dirBlock.lookupGetPB.serverHint.aSocket = 0;
  418.     dirBlock.lookupGetPB.dsRefNum = gAOCESetupDSRef;
  419.     dirBlock.lookupGetPB.identity = gLocalIdentity;
  420.     dirBlock.lookupGetPB.aRecordList = recordList;
  421.     dirBlock.lookupGetPB.attrTypeList = attrList;
  422.     dirBlock.lookupGetPB.recordIDCount = 1;
  423.     dirBlock.lookupGetPB.attrTypeCount = 1;
  424.     dirBlock.lookupGetPB.includeStartingPoint = false;
  425.     dirBlock.lookupGetPB.getBuffer = buff;
  426.     dirBlock.lookupGetPB.getBufferSize = kAttrBufferSize;
  427.     dirBlock.lookupGetPB.startingRecordIndex = 1;
  428.     dirBlock.lookupGetPB.startingAttrTypeIndex = 1;
  429.     dirBlock.lookupParsePB.eachRecordID = RecordIDCallback;
  430.     dirBlock.lookupParsePB.eachAttrType = nil;
  431.     dirBlock.lookupParsePB.eachAttrValue = SingleAttrValueCallback;
  432.     OCESetCreationIDtoNull(&dirBlock.lookupGetPB.startingAttribute.cid);
  433.     
  434.     err = DirLookupGet(&dirBlock,false);
  435.     if (err==noErr || err==kOCEMoreData)
  436.         err = DirLookupParse(&dirBlock,false);
  437.     
  438.     DisposPtrChk(buff);
  439.     return err;
  440. }
  441.  
  442.  
  443. pascal Boolean RecordIDCallback(long clientData, const RecordID *recordID)
  444. {
  445.     #pragma unused (clientData,recordID)
  446.     
  447.     return false;
  448. }
  449.  
  450.  
  451. pascal Boolean SingleAttrValueCallback(long clientData, const Attribute *attribute)
  452. {
  453.     AttributeCopyInfoPtr callbackInfo;
  454.     Size moveSize;
  455.     
  456.     callbackInfo = (AttributeCopyInfoPtr) clientData;
  457.     
  458.     moveSize = attribute->value.dataLength;
  459.     if (moveSize>callbackInfo->bufferSize)
  460.         moveSize = callbackInfo->bufferSize;
  461.     BlockMove(attribute->value.bytes,callbackInfo->buffer,moveSize);
  462.     return false;
  463. }
  464.  
  465.  
  466. pascal Boolean AddSlotCallback(long clientData, const Attribute *attribute)
  467. {
  468.     #pragma unused (clientData)
  469.     SlotSpec *newSlot;
  470.     PackedRecordIDPtr packedRID;
  471.     RecordID rid;
  472.     
  473.     newSlot = &gSlotDatabase[gNumSlots++];
  474.     
  475.     packedRID = (PackedRecordIDPtr) attribute->value.bytes;
  476.     OCEUnpackRecordID(packedRID,&rid);
  477.     OCECopyCreationID(&rid.local.cid,&newSlot->slotCID);
  478.  
  479.     return false;    // continue
  480. }
  481.  
  482.  
  483. // AddAttribute
  484. //
  485. // add an attribute value to a record
  486. //
  487. // note: this can be can be called in response to an EPPC handled by the "alternate" event loop
  488. //       this is why we 
  489. OSErr AddAttribute(CreationID *cid,short dsRef,AttributeType *attribType,void *data,unsigned long dataLength,AttributeTag tag)
  490. {
  491.     DirParamBlock attrBlock;
  492.     RecordID recordID;
  493.     Attribute attribute;
  494.     OSErr err;
  495.     
  496.     MakePersonalRecordID(&recordID,cid);    
  497.     
  498.     attrBlock.addAttributeValuePB.serverHint.aNet = 0;
  499.     attrBlock.addAttributeValuePB.serverHint.aNode = 0;
  500.     attrBlock.addAttributeValuePB.serverHint.aSocket = 0;
  501.     attrBlock.addAttributeValuePB.dsRefNum = dsRef;
  502.     attrBlock.addAttributeValuePB.identity = gLocalIdentity;
  503.     attrBlock.addAttributeValuePB.aRecord = &recordID;
  504.     attrBlock.addAttributeValuePB.attr = &attribute;
  505.  
  506.     ClearBuffer(&attribute,sizeof(Attribute));
  507.     err = OCECopyRString((const RString *)attribType, (RString *)&attribute.attributeType,kAttributeTypeMaxBytes);
  508.     if (err!=noErr)
  509.         return err;
  510.     attribute.value.tag = tag;
  511.     attribute.value.dataLength = dataLength;
  512.     attribute.value.bytes = (Ptr)data;
  513.     err = DirAddAttributeValue(&attrBlock,false);
  514.  
  515.     return err;
  516. }
  517.  
  518.  
  519.  
  520. void CloseGatewayStuff(void)
  521. {
  522. }
  523.  
  524.  
  525. OSErr InitAOCEStuff(void)
  526. {
  527.     return noErr;
  528. }
  529.  
  530.  
  531. void CloseAOCEStuff(void)
  532. {
  533.     ExitAuthStuff();
  534. }
  535.  
  536.  
  537. // HasAOCE
  538. //
  539. // returns true only of AOCE is available and running
  540. //
  541. Boolean HasAOCE(void)
  542. {
  543.     OSErr err;
  544.     long response;
  545.     
  546.     if (!TrapAvailable(_GestaltDispatch))
  547.         return false;
  548.     
  549.     err = Gestalt(gestaltOCEToolboxAttr,&response);
  550.     if (err!=noErr)
  551.         return false;
  552.         
  553.     return (response && (response << gestaltOCETBAvailable));
  554. }
  555.  
  556.  
  557. // MakePersonalRecordID
  558. //
  559. // this convenience function fills in a RecordID given a creation ID, since a fully specified
  560. // record ID for a personal directory contains only a creation ID
  561. //
  562. void MakePersonalRecordID(RecordID *recordID,CreationID *creationID)
  563. {
  564.     recordID->rli = nil;
  565.     OCECopyCreationID(creationID,&recordID->local.cid);
  566.     recordID->local.recordName = nil;
  567.     recordID->local.recordType = nil;
  568. }
  569.  
  570.  
  571. // GetSlotSpecFromID
  572. //
  573. // given a slot ID this function returns the corresponding slot info record which we store
  574. // for each slot
  575. //
  576. SlotSpec *GetSlotSpecFromID(short slotID)
  577. {
  578.     short index;
  579.     
  580.     for (index=0; index<gNumSlots; index++)
  581.         if (gSlotDatabase[index].slotID==slotID)
  582.             return &gSlotDatabase[index];
  583.     
  584.     return nil;
  585. }
  586.  
  587.  
  588. void MacToMailTime(unsigned long macTime,MailTime *mailTime)
  589. {
  590.     mailTime->time = macTime + (8*60*60);    // assume pacific time for now (hack)
  591.     mailTime->offset = (8*60*60);
  592. }
  593.  
  594.  
  595. void r2cString (RString *rStr,char *cStr)
  596. {
  597.     StringPtr pStr;
  598.     
  599.     pStr = OCERToPString(rStr);
  600.     pstrcpy((StringPtr)cStr,pStr);
  601.     p2cstr((StringPtr)cStr);
  602. }
  603.  
  604.  
  605. // this routine copies as many bytes from rstr1 to rstr2, truncating rstr2 if there isn't
  606. // enough space
  607. //
  608. OSErr OCECopyFitRString (RString *str1, RString *str2, unsigned short str2Length)
  609. {
  610.     unsigned short saveLength;
  611.     OSErr err;
  612.     
  613.     saveLength = str1->dataLength;
  614.     
  615.     if (str2Length<str1->dataLength)
  616.         str1->dataLength = str2Length;
  617.     
  618.     err = OCECopyRString(str1,str2,str2Length);
  619.     str1->dataLength = saveLength;
  620.     return err;
  621. }
  622.  
  623.  
  624. pascal void MSAMCompletion(MSAMParam *gwp)
  625. {
  626.     long saveA5;
  627.     
  628.     saveA5 = SetA5((long)gwp->header.saveA5);
  629.  
  630.     gWakeUpSecondary = true;                    // set a flag in case we get caught
  631.     WakeUpProcess(&gOurPSN);                    // in between check and WaitNextEvent...
  632.  
  633.     SetA5(saveA5);
  634. }
  635.